package com.cy.stone.system.application.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.cy.stone.framework.redis.RedisKey;
import com.cy.stone.framework.redis.RedisUtil;
import com.cy.stone.system.application.RoleMenuApi;
import com.cy.stone.system.domain.clientobject.role.RoleMenuCO;
import com.cy.stone.system.infrastructure.database.entity.MenuEntity;
import com.cy.stone.system.infrastructure.database.entity.RoleMenuEntity;
import com.cy.stone.system.infrastructure.database.service.IMenuService;
import com.cy.stone.system.infrastructure.database.service.IRoleMenuService;
import com.mybatisflex.core.logicdelete.LogicDeleteManager;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

import static com.cy.stone.system.infrastructure.database.table.RoleMenuTableDef.ROLE_MENU_ENTITY;

/**
 * 角色权限接口实现类
 * @author Wings
 * @since 2023-12-10
 */
@Component
@RequiredArgsConstructor
public class RoleMenuApiImpl implements RoleMenuApi {

    private final IRoleMenuService roleMenuService;

    private final IMenuService menuService;

    @Override
    public List<String> cachePermission(String roleCode) {
        List<RoleMenuEntity> roleMenus = roleMenuService.list(QueryWrapper.create().from(ROLE_MENU_ENTITY)
                .where(ROLE_MENU_ENTITY.ROLE_CODE.eq(roleCode)));
        if (CollUtil.isNotEmpty(roleMenus)) {
            List<String> menuIds = roleMenus.stream().map(RoleMenuEntity::getMenuId).distinct().toList();
            List<MenuEntity> menus = menuService.listByIds(menuIds);
            List<String> permissions = menus.stream().map(MenuEntity::getPerms).toList();
            // 缓存
            RedisUtil.setCacheObject(RedisKey.ROLE_KEY + roleCode, JSONUtil.toJsonStr(permissions));
            return permissions;
        } else {
            return new ArrayList<>();
        }
    }

    @Override
    public void menuRelate(RoleMenuCO roleMenuCO) {
        // 先删除该角色旧的关联数据
        LogicDeleteManager.execWithoutLogicDelete(() -> {
            roleMenuService.remove(QueryWrapper.create().from(ROLE_MENU_ENTITY)
                    .where(ROLE_MENU_ENTITY.ROLE_CODE.eq(roleMenuCO.getRoleCode())));
        });
        // 插入新的关联数据
        List<RoleMenuEntity> list = RoleMenuCO.toEntities(roleMenuCO);
        roleMenuService.saveBatch(list);
        // 更新缓存数据
        RedisUtil.deleteObject(RedisKey.ROLE_KEY + roleMenuCO.getRoleCode());
        cachePermission(roleMenuCO.getRoleCode());
    }
}
